//------------------------------------------------------------------------------
//
//   author: 小兵（aosnow@yeah.net）
//   create: 2012-5-26 上午11:51:32
//    class: HttpRequestMessage - Http请求的描述信息，包含一条请求所需要的配置
//
//------------------------------------------------------------------------------

package starfire.rpc.http
{
	import flash.errors.IllegalOperationError;
	import flash.net.URLRequestHeader;

	import starfire.namespaces.sn_internal;

	public final class HttpRequestMessage
	{

		public var command:String;

		//--------------------------------------------------------------------------
		//
		// Static Constants
		// 
		//--------------------------------------------------------------------------

		/** 发送数据内容的 MIME 类型为：<code>"application/json"</code> **/
		public static const CONTENT_TYPE_JSON:String = "application/json";

		/** 发送数据内容的 MIME 类型为：<code>"application/xml"</code> **/
		public static const CONTENT_TYPE_XML:String = "application/xml";

		/** 发送数据内容的 MIME 类型为（默认类型）：<code>"application/x-www-form-urlencoded"</code> **/
		public static const CONTENT_TYPE_FORM:String = "application/x-www-form-urlencoded";

		/** 发送数据内容的 MIME 类型为：<code>"text/xml; charset=utf-8"</code> **/
		public static const CONTENT_TYPE_SOAP_XML:String = "text/xml; charset=utf-8";

		/** 以 <code>POST</code> 形式发送 HTTP 服务请求  **/
		public static const METHOD_POST:String = "POST";

		/** 以 <code>GET</code> 形式发送 HTTP 服务请求  **/
		public static const METHOD_GET:String = "GET";

		public function HttpRequestMessage()
		{
		}

		//--------------------------------------------------------------------------
		//
		// Properties
		// 
		//--------------------------------------------------------------------------

		private var _method:String;
		private var _contentType:String;
		private var _resultFormat:String;
		private var _url:String;
		private var _timeOut:uint;
		private var _data:Object;
		private var _keyData:Object;
		private var _inactive:Boolean;

		//----------------------------------------
		//  resultFormat
		//----------------------------------------

		public function get resultFormat():String
		{
			return _resultFormat;
		}

		/**
		 * 指示如何反序列化由 HTTP 调用返回的结果的值。该项目的值可能的值：
		 * <ul>
		 * <li>RESULT_FORMAT_FLASHVARS：返回的值是包含由 &amp; 符号分隔的名称=值对的文本，该文本被分析为 Object</li>
		 * <li>RESULT_FORMAT_JSON：返回的值是 JSON 格式文本，并且按照 Object 对象树分析。</li>
		 * <li>RESULT_FORMAT_OBJECT（默认值）：返回的值为 {name:value} 格式文本，并且按照 Object 对象树分析，与返回值结构相同。
		 * 值的结构中，可以包含 {} 结构嵌套，但数据值只能为基本数据类型（数值、字符串、布尔值、NaN、Null）。要使用复杂数据类型，
		 * 请改用 JSON 格式数据返回。</li>
		 * <li>RESULT_FORMAT_TEXT：返回的值为文本并且未经处理。文本形式的原始内容。</li>
		 * <li>RESULT_FORMAT_XML：返回的值为 XML 格式文本，并且自动转换为  XML 对象返回</li>
		 * </ul>
		 * <p>这些常量可以通过 HttpResult 类来访问。</p>
		 *
		 * @param value HttpResult 中规定的类型
		 */
		public function set resultFormat( value:String ):void
		{
			if( value == HttpResult.RESULT_FORMAT_BINARY )
				throw new IllegalOperationError( "无须设置 HttpResult.RESULT_FORMAT_BINARY 类型，" //
												 + "当提交数据为 ByteArray 类型时，" //
												 + "系统会自动使用此类型来返回 ByteArray 结果。" );

			_resultFormat = value;
		}

		/**
		 * 该 HttpRequestMessage 对象是否已经沦为待用的就绪状态
		 * <p>当某个服务，使用此 Http 配置信息已经发送出了请求，则会立即将此对象认定为待用的就绪状态，
		 * 以待其它服务能够继续重用这个对象</p>
		 */
		public function get inactive():Boolean
		{
			return _inactive;
		}

		sn_internal function setInactive( value:Boolean ):void
		{
			_inactive = value;
		}

		public function get keyData():Object
		{
			_keyData = _keyData || {};

			return _keyData;
		}

		/**
		 * 用于与服务端进行相互验证的附加密匙信息
		 * @param value					- 数据信息
		 */
		public function set keyData( value:Object ):void
		{
			_keyData = value;
		}

		public function get data():Object
		{
			return _data;
		}

		/**
		 * 请求服务时发送的数据
		 * <p>一般发送包含指定值对的对象，例如：
		 * <ul>
		 * <code>data = {username:"名字", playerId:"1000021"};</code>
		 * </ul>
		 * </p>
		 * <p>
		 * 若设置要发送的数据为 ByteArray 类型，则将强制以字节流形式向指定服务地址发送。
		 * 这也就要求服务地址能够处理字节流的能力。并且，得到的结果也将是字节流。一般不推荐这样做。
		 * </p>
		 * @param value					- 需要发送的数据
		 */
		public function set data( value:Object ):void
		{
			_data = value;
		}

		public function get timeOut():uint
		{
			return _timeOut;
		}

		/**
		 * 请求服务的超时时间（单位：秒，超时后将自动结束请求）
		 * @param value					- 超时时间（单位：秒）
		 */
		public function set timeOut( value:uint ):void
		{
			_timeOut = value;
		}

		public function get url():String
		{
			return _url;
		}

		/**
		 * 所请求的 URL
		 * @param value					- 地址描述
		 */
		public function set url( value:String ):void
		{
			_url = value;
		}

		/**
		 * 发送请求时的请求类型，参数必须为以下两者之一：
		 * <code>
		 * <li>HttpRequestMessage.GET</li>
		 * <li>HttpRequestMessage.POST</li>
		 * </code>
		 */
		public function set method( value:String ):void
		{
			_method = value;
		}

		public function get method():String
		{
			return _method;
		}

		/**
		 * data 属性中内容的 MIME 内容类型。
		 * <p>默认值为 application/x-www-form-urlencoded。</p>
		 * <p><strong>注意：</strong>FileReference.upload()、FileReference.download() 和 HTMLLoader.load() 方法不支持 URLRequest.contentType 属性。</p>
		 * <p>发送 POST 请求时，contentType 和 data 属性的值必须正确对应。contentType 属性的值表示服务器如何解释 data 属性的值。 </p>
		 * <UL>
		 *   <li>如果 data 属性的值是一个 URLVariables 对象，则 contentType 的值必须是 application/x-www-form-urlencoded。</li>
		 *   <li>如果 data 属性的值为其他类型，则 contentType 的值应表示将要发送的 POST 数据的类型（该数据为 data 属性的值中包含的二进制或字符串数据）。</li>
		 *   <li>对于 FileReference.upload()，请求的内容类型将自动设置为   multipart/form-data 并忽略 contentType 属性的值。</li>
		 * </UL>
		 * <p>在 Flash Player 10 和更高版本中，如果使用包含上载（由 POST 体内的“content-disposition”标头中的“filename”参数表示）的 multipart Content-Type（例如 “multipart/form-data”），则 POST 操作会受应用于上载的安全规则的约束：</p>
		 * <UL>
		 *   <li>必须执行 POST 操作以响应用户启动的操作（如鼠标单击或按键）。</li>
		 *   <li>如果 POST 操作是跨域的（POST 目标与发送 POST 请求的 SWF 文件不在同一台服务器上），则目标服务器必须提供一个允许跨域访问的 URL 策略文件。</li>
		 * </UL>
		 * <p>另外，对于任何 multipart Content-Type，语法必须有效（根据 RFC2046 标准）。如果语法无效，则 POST 操作受应用于上载的安全规则约束。</p>
		 */
		public function set contentType( value:String ):void
		{
			_contentType = value;
		}

		public function get contentType():String
		{
			return _contentType;
		}

		//--------------------------------------------------------------------------
		//
		// Method
		// 
		//--------------------------------------------------------------------------

		public var httpHeaders:Vector.<URLRequestHeader>;

		/**
		 * 新添加HTTP请求的头信息（重复添加同名头信息，相当于覆盖之前设置的头信息数据）
		 * <p><b>注意</b>：只有 HttpRequestMessage.METHOD_POST 形式发送数据时，才支持此功能。</p>
		 * @param header					- 头信息值对
		 */
		public function addHttpHeader( header:URLRequestHeader ):void
		{
			httpHeaders = httpHeaders || new Vector.<URLRequestHeader>;

			if( header )
			{
				var index:int = httpHeaders.indexOf( header );

				if( index == -1 )
				{
					httpHeaders.push( header );
				}
				else
				{
					httpHeaders[ index ].value = header.value;
				}
			}
		}

		/**
		 * 从已添加的头信息中移除指定名称的头信息（移除成功则返回 true）
		 * @param headerName				- 头名称
		 */
		public function removeHttpHeader( headerName:String ):Boolean
		{
			if( httpHeaders && httpHeaders.length > 0 )
			{
				var index:int = -1;

				for each( var h:URLRequestHeader in httpHeaders )
				{
					if( h.name == headerName )
					{
						index = httpHeaders.indexOf( h );
						break;
					}
				}

				if( index > -1 )
				{
					httpHeaders.splice( index, 1 );
					return true;
				}
			}

			return false;
		}
	}
}
